package com.insight.common.util;

import java.net.InetAddress;

/**
 * @Description: UUID生成工具类，生成唯一32位UUID字符串，适用于分布式环境
 * @Author: 自动补全
 * @Date: 2024-07-01
 */
public class UUIDGenerator {

	/**
	 * 产生一个32位的UUID
	 * @return 唯一32位UUID字符串
	 */
	public static String generate() {
		return format(getIP()) +
                format(getJVM()) + format(getHiTime()) +
                format(getLoTime()) + format(getCount());

	}

    /**
     * 本地IP地址int值
     */
	private static final int IP;
	static {
		int ipadd;
		try {
			InetAddress address = InetAddress.getLocalHost();
			if (address == null) {
				ipadd = 0;
			} else {
				byte[] bytes = address.getAddress();
				ipadd = toInt(bytes);
			}
		} catch (Exception e) {
			ipadd = 0;
		}
		IP = ipadd;
	}

    /**
     * 计数器
     */
    private static short counter = (short) 0;

    /**
     * JVM唯一标识
     */
    private static final int JVM = (int) (System.currentTimeMillis() >>> 8);

	private static String format(int intval) {
		String formatted = Integer.toHexString(intval);
		StringBuilder buf = new StringBuilder("00000000");
		buf.replace(8 - formatted.length(), 8, formatted);
		return buf.toString();
	}

	private static String format(short shortval) {
		String formatted = Integer.toHexString(shortval);
		StringBuilder buf = new StringBuilder("0000");
		buf.replace(4 - formatted.length(), 4, formatted);
		return buf.toString();
	}

	/**
	 * 获取JVM唯一标识
	 * @return JVM唯一标识
	 */
	private static int getJVM() {
		return JVM;
	}

	/**
	 * 获取自增计数器，线程安全
	 * @return 计数器值
	 */
	private static short getCount() {
		synchronized (UUIDGenerator.class) {
			if (counter < 0) {
				counter = 0;
			}
			return counter++;
		}
	}

	/**
	 * 获取本地IP地址的int值
	 * @return IP地址int值
	 */
	private static int getIP() {
		return IP;
	}

	/**
	 * 获取高位时间戳，精确到毫秒
	 * @return 高位时间戳
	 */
	private static short getHiTime() {
		return (short) (System.currentTimeMillis() >>> 32);
	}

	/**
	 * 获取低位时间戳，精确到毫秒
	 * @return 低位时间戳
	 */
	private static int getLoTime() {
		return (int) System.currentTimeMillis();
	}

	/**
	 * 字节数组转int
	 * @param bytes 字节数组
	 * @return int值
	 */
	private static int toInt(byte[] bytes) {
		int result = 0;
		for (int i = 0; i < 4; i++) {
			result = (result << 8) | (bytes[i] & 0xFF);
		}
		return result;
	}

}
